//
//  MainViewController.m
//  Bluetooth_iOS
//
//  Created by 魏延(颜魏) on 2023/3/13.
//

#import "UpgardeViewController.h"
#import "BTManager.h"
#import "CEDeviceListViewController.h"
#import "ProgressHUD.h"
#import "GlobalDefine.h"

@interface UpgardeViewController ()<UIDocumentPickerDelegate>

@property (weak, nonatomic) IBOutlet UIView *bgView;
@property (weak, nonatomic) IBOutlet UILabel *filePathLabel;
@property (weak, nonatomic) IBOutlet UIButton *connectBtn;
@property (weak, nonatomic) IBOutlet UIButton *upgradeBtn;
@property (weak, nonatomic) IBOutlet UIButton *cleanBtn;
@property (weak, nonatomic) IBOutlet UIView *progressView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *progressViewWidth;
@property (weak, nonatomic) IBOutlet UILabel *contentLabel;
@property (weak, nonatomic) IBOutlet UILabel *progressLabel;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *progressLeft;
@property (weak, nonatomic) IBOutlet UITextView *contentTV;
@property (weak, nonatomic) IBOutlet UIButton *oldBluetoothBtn;
@property (weak, nonatomic) IBOutlet UIButton *ewBluetoothBtn;
@property (weak, nonatomic) IBOutlet UILabel *statusLabel;

@property (weak, nonatomic) IBOutlet UILabel *tipsLabel1;
@property (weak, nonatomic) IBOutlet UILabel *tipsLabel2;
@property (weak, nonatomic) IBOutlet UIButton *tipsBtn3;
@property (weak, nonatomic) IBOutlet UILabel *tipsLabel4;
@property (weak, nonatomic) IBOutlet UILabel *tipsLabel5;


@end

@implementation UpgardeViewController
{
    NSData *fileData;//[1024 + 9];
    int binFileSize_k;     //bin文件大小，以K为单位
    int binFileResidualSize;  //bin文件大小，以K为单位后剩余的大小
    int sentCount_k;  //已经发送了多少k
    int sendLenght_byte;//已经发送了多少字节
    bool upgradingFlag;
    bool upgradingConnectCommandFlag;
    int connectCount;
    int dataIndex;
    int sendTime;
    bool isUpgradingSlice;
    // 升级是否可用
    bool isUpgradAvailable;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [[BTManager sharedBTManager] startScan];
    
    self.tipsLabel1.text = NSLocalizedString(@"Upgrade", @"");
    self.tipsLabel2.text = NSLocalizedString(@"Bin file：", @"");
    [self.tipsBtn3 setTitle:NSLocalizedString(@"Browse", @"") forState:UIControlStateNormal];
    self.tipsLabel4.text = NSLocalizedString(@"progress：", @"");
    [self.upgradeBtn setTitle:NSLocalizedString(@"Start", @"") forState:UIControlStateNormal];
    [self.cleanBtn setTitle:NSLocalizedString(@"Clear", @"") forState:UIControlStateNormal];
    [self.oldBluetoothBtn setTitle:NSLocalizedString(@"Old Bluetooth", @"") forState:UIControlStateNormal];
    [self.ewBluetoothBtn setTitle:NSLocalizedString(@"New Bluetooth", @"") forState:UIControlStateNormal];
    self.tipsLabel5.text = NSLocalizedString(@" Upgrade Firmware ", @"");

    self.bgView.layer.cornerRadius = 6;
    self.bgView.layer.masksToBounds = YES;
    self.bgView.layer.borderWidth = 1;
    self.bgView.layer.borderColor = [[UIColor grayColor] colorWithAlphaComponent:0.4].CGColor;

    self.filePathLabel.layer.cornerRadius = 2;
    self.filePathLabel.layer.masksToBounds = YES;
    self.filePathLabel.layer.borderWidth = 1;
    self.filePathLabel.layer.borderColor = [[UIColor grayColor] colorWithAlphaComponent:0.4].CGColor;

    self.contentLabel.layer.cornerRadius = 2;
    self.contentLabel.layer.masksToBounds = YES;
    self.contentLabel.layer.borderWidth = 1;
    self.contentLabel.layer.borderColor = [[UIColor grayColor] colorWithAlphaComponent:0.4].CGColor;

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reciveData:) name:kBTDidReciveData object:nil];
//    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(connectSuccess:) name:kBTConnectionSucceed object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(connectFail:) name:kBTDisconnect object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(upgradeFail:) name:kBTUpgradeFail object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sendError:) name:@"sendError" object:nil];
    
    sentCount_k = 0;
    sendLenght_byte = 0;
    upgradingFlag = NO;
    upgradingConnectCommandFlag = NO;
    connectCount = 0;
    dataIndex = 0;
    sendTime = 50;
    isUpgradingSlice = NO;
    isUpgradAvailable = NO;
    
    [self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(actionTap)]];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [[NSNotificationCenter defaultCenter] postNotificationName:kBTUpgrading object:@(1)];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    upgradingConnectCommandFlag = YES;
    [[NSNotificationCenter defaultCenter] postNotificationName:kBTUpgrading object:@(0)];
}

- (void)actionTap {
    [self.contentTV endEditing:YES];
}

- (IBAction)actionBack:(id)sender {
    [self.navigationController popViewControllerAnimated:YES];
}

- (IBAction)actionType:(id)sender {
    [BTManager sharedBTManager].type = 0;
    self.oldBluetoothBtn.backgroundColor = [UIColor redColor];
    self.ewBluetoothBtn.backgroundColor = [UIColor lightGrayColor];
}

- (IBAction)actionType1:(id)sender {
    [BTManager sharedBTManager].type = 1;
    self.oldBluetoothBtn.backgroundColor = [UIColor lightGrayColor];
    self.ewBluetoothBtn.backgroundColor = [UIColor redColor];
}

#pragma mark - action
- (IBAction)actionOpenFile:(id)sender {
    if (upgradingFlag) {
        return;
    }
//    [self loadFileData];
    [self selectFile];
}

- (IBAction)actionConnectDevice:(id)sender {
    if ([BTManager sharedBTManager].peripheral) {
        [[BTManager sharedBTManager] disconnectRootPeripheral];
    }
    CEDeviceListViewController *vc = [[CEDeviceListViewController alloc] initWithNibName:@"CEDeviceListViewController" bundle:nil];
    [self.navigationController pushViewController:vc animated:YES];
}

- (IBAction)actionUpgrade:(id)sender {
    if (!fileData) {
        [ProgressHUD showErrorMessage:NSLocalizedString(@"Please select bin file.", @"")];
        return;
    }
    [self actionUpgrading];
}

- (IBAction)actionClean:(id)sender {
    sentCount_k = 0;
    sendLenght_byte = 0;
    upgradingFlag = NO;
    upgradingConnectCommandFlag = NO;
    connectCount = 0;
    dataIndex = 0;
    isUpgradingSlice = NO;
    isUpgradAvailable = NO;

    self.filePathLabel.text = @"";
    self.contentLabel.text = @"";
    self.progressViewWidth.constant = 0;
    self.contentTV.text = NSLocalizedString(@"日志：\n", @"");
}

- (void)selectFile {
    NSArray *types = @[@"public.data"];
    UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:types inMode:UIDocumentPickerModeOpen];
    documentPicker.delegate = self;
    documentPicker.modalPresentationStyle = UIModalPresentationFullScreen;
    [self  presentViewController:documentPicker animated: YES  completion: nil];
}

- (void)loadFileData:(NSString *)path data:(NSData *)data {
    fileData = data;
    self.contentLabel.text = [NSString stringWithFormat:@"%@", fileData];
    binFileSize_k = (int)fileData.length / 1024;     //的到有多少K
    binFileResidualSize = fileData.length % 1024; //得到多出来的字节数
    self.filePathLabel.text = path;
    
//    Byte *dataBytes = (Byte*)fileData.bytes;
//    for (NSInteger i=0; i<binFileSize_k+1; i++) {
//        int length = i == binFileSize_k ? binFileSize_k : 1024;
//        Byte sendbuf[length];
//        NSString *cmd = @"0x";
//        for (int j=0; j<length; j++) {
//            sendbuf[j] = dataBytes[i*1024 + j];
//            cmd = [NSString stringWithFormat:@"%@%@", cmd, [self tenSixtoHex:sendbuf[j]]];
//        }
//        NSLog(@"%ld--------%@", (long)i, cmd);
//    }
    
    [self sendUpgradeConnectCommand]; //发送在线升级连接指令

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        if (!self->upgradingConnectCommandFlag) {
            self->isUpgradAvailable = NO;
            [ProgressHUD hideHUD];
            [self sendUpgradeConnectCommand];
        }
    });
    
    /* 进度条清零 */
    /* 进度条改变 */
    self.progressViewWidth.constant = 0;
}

//- (void)loadFileData {
//    NSString *path = [[NSBundle mainBundle] pathForResource:@"shenji1" ofType:@"bin"];
//    NSFileManager *fm = [NSFileManager defaultManager];
//    fileData = [fm contentsAtPath:path];
//    self.contentLabel.text = [NSString stringWithFormat:@"%@", fileData];
//    binFileSize_k = (int)fileData.length / 1024;     //的到有多少K
//    binFileResidualSize = fileData.length % 1024; //得到多出来的字节数
//    self.filePathLabel.text = path;
//    
////    Byte *dataBytes = (Byte*)fileData.bytes;
////    for (NSInteger i=0; i<binFileSize_k+1; i++) {
////        int length = i == binFileSize_k ? binFileSize_k : 1024;
////        Byte sendbuf[length];
////        NSString *cmd = @"0x";
////        for (int j=0; j<length; j++) {
////            sendbuf[j] = dataBytes[i*1024 + j];
////            cmd = [NSString stringWithFormat:@"%@%@", cmd, [self tenSixtoHex:sendbuf[j]]];
////        }
////        NSLog(@"%ld--------%@", (long)i, cmd);
////    }
//    
//    [self sendUpgradeConnectCommand]; //发送在线升级连接指令
//
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//        if (!self->upgradingConnectCommandFlag) {
//            self->isUpgradAvailable = NO;
//            [ProgressHUD hideHUD];
//            [self sendUpgradeConnectCommand];
//        }
//    });
//    
//    /* 进度条清零 */
//    /* 进度条改变 */
//    self.progressViewWidth.constant = 0;
//    self.statusLabel.text = @"";
//}

- (void)actionUpgrading {
//    if (![BTManager sharedBTManager].peripheral) {
//        [ProgressHUD showErrorMessage:@"请连接蓝牙"];
//        return;;
//    }
    
    if (!isUpgradAvailable) {
        [self sendUpgradeConnectCommand];
        [ProgressHUD showErrorMessage:NSLocalizedString(@"Applying for upgrade connection, please wait~", @"")];
        return;
    }

    if (fileData != nil && !upgradingFlag) {
        upgradingFlag = YES;
        [ProgressHUD showActivityMessageInView:NSLocalizedString(@"Upgrading...", @"")];
        [self startUpgrading];
        NSLog(@"正在升级！");
    }
}

- (void)startUpgrading {
    /* 升级标志置一 */
    if(upgradingFlag) {
       /* 如果发送完成 */
        if(sendLenght_byte >= (binFileSize_k*1024 + binFileResidualSize)) {
            [self sendUpgradeCompleteCommand];
            fileData = nil;
            binFileSize_k = 0;     //bin文件大小，以K为单位
            binFileResidualSize = 0;  //bin文件大小，以K为单位后剩余的大小
            sentCount_k = 0;  //已经发送了多少k
            sendLenght_byte = 0;//已经发送了多少字节
            upgradingFlag = NO;
            dataIndex = 0;

           /* 进度条改变 */
            self.progressViewWidth.constant = 160;
            self.progressLabel.text = @"100%";
            [ProgressHUD hideHUD];
            [ProgressHUD showErrorMessage:NSLocalizedString(@"Upgrade completed", @"")];
            self.statusLabel.text = NSLocalizedString(@"Upgrade completed", @"");
        }else {
            /* 进度条改变 */
//            self.progressViewWidth.constant = self->sentCount_k*100/self->binFileSize_k;
            [self flashUpgrate];
        }
    }
}

- (void)flashUpgrate {
    dataIndex += 1;
    sentCount_k += 1;

    Byte senddataTemp[1024 + 9];
    int j = 0;

    senddataTemp[j++] = 0x01;       //地址
    senddataTemp[j++] = 0x10;       //命令
    senddataTemp[j++] = 0xFF;  //地址高
    senddataTemp[j++] = 0xFE;  //地址低

    Byte *binFileArray = (Byte*)fileData.bytes;
    /* 已经发送k为单位的字节数，判断是否有余数有的话发送余数 */
    if ((sentCount_k == binFileSize_k+1) && (binFileResidualSize != 0)) {
        senddataTemp[j++] = (Byte)(binFileResidualSize / 256); //寄存器数量 == 字节数（不是标准modbus）
        senddataTemp[j++] = (Byte)(binFileResidualSize % 256);
        senddataTemp[j++] = (Byte)0;         //字节数

        for (int i=0; i<binFileResidualSize; i++) {
            senddataTemp[j++] = binFileArray[i+sendLenght_byte];
        }

        int crcValue = [self crcCheck:senddataTemp length:j];
        senddataTemp[j++] = (Byte)crcValue;
        senddataTemp[j++] = (Byte)(crcValue >> 8);

        Byte sendbuf[9 + binFileResidualSize];
        for (int i=0; i<9 + binFileResidualSize; i++) {
            sendbuf[i] = senddataTemp[i];
        }

        sendLenght_byte += binFileResidualSize;
        [self sliceUpload:[[NSData alloc] initWithBytes:sendbuf length:9 + binFileResidualSize] length:9 + binFileResidualSize index:dataIndex];
    }else {
        senddataTemp[j++] = 0x04;// (1024 / 256);
        senddataTemp[j++] = (Byte)(1024 % 256);
        senddataTemp[j++] = (Byte)1024;

        for (int i=0; i<1024; i++) {
            senddataTemp[j++] = binFileArray[i+sendLenght_byte];
        }

        int crcValue = [self crcCheck:senddataTemp length:j];
        senddataTemp[j++] = (Byte)crcValue;
        senddataTemp[j++] = (Byte)(crcValue >> 8);

        sendLenght_byte += 1024;         //计算已经发送的大小
        [self sliceUpload:[[NSData alloc] initWithBytes:senddataTemp length:9 + 1024] length:9 + 1024 index:dataIndex];
    }
}

- (void)sliceUpload:(NSData *)data length:(int)length index:(int)index {
    int count = (length/20 + 1);
    Byte *dataBytes = (Byte*)data.bytes;
//    NSString *cmd = @"0x";
//    for (int j=0; j<data.length; j++) {
//        cmd = [NSString stringWithFormat:@"%@%@", cmd, [self tenSixtoHex:dataBytes[j]]];
//    }
//    NSLog(@"%ld--------%@", (long)index, cmd);
    for (int i=0; i<count; i++) {
        int ct = i != count-1 ? 20 : (length % 20);
        Byte sendbuf[ct];
        for (int j=0; j<20; j++) {
            if (i*20 + j < length) {
                sendbuf[j] = dataBytes[i*20 + j];
            }
        }
        
//        self.contentTV.text = [NSString stringWithFormat:@"%@\nsection=%d,row=%d：%@", self.contentTV.text, index, i, cmd];
        NSLog(@"%d-%d-------%@", index, i, [[NSData alloc] initWithBytes:sendbuf length:ct]);
//        sleep(sendTime / 1000.0);
        [NSThread sleepForTimeInterval:sendTime / 1000.0];
        [self sendData:[[NSData alloc] initWithBytes:sendbuf length:ct] index:index isLastSliceIndex:i==count-1];
    }
}

- (NSString *)tenSixtoHex:(long long int) num{
    NSString *result = [NSString stringWithFormat:@"%llx",num];
    if (result.length == 1) {
        return [NSString stringWithFormat:@"0%@", result.lowercaseString];
    }
    return [result lowercaseString];
}

- (void)sendData:(NSData *)dataBuf index:(int)index isLastSliceIndex:(BOOL)isLastSliceIndex {
    [[BTManager sharedBTManager] sendCommand:(Byte*)dataBuf.bytes length:(int)dataBuf.length];
    isUpgradingSlice = !isLastSliceIndex;
    int totalCount = binFileSize_k + (binFileResidualSize > 0 ? 1 : 0);
    if (isLastSliceIndex) {
        self.progressLabel.text = [NSString stringWithFormat:@"%.0f%%", MIN((index + 1.0) / (totalCount * 1.0), 1) * 100];
        self.progressViewWidth.constant = 160.0 / totalCount * (index + 1);
        self.progressLeft.constant = self.progressViewWidth.constant + 10;
//        
//        sleep(2);
//        [self startUpgrading];
    }
}

- (void)connectFail:(NSNotification *)nf {
    self.contentTV.text = [NSString stringWithFormat:@"%@\n%@", self.contentTV.text, @"蓝牙连接断开了------"];
}
- (void)sendError:(NSNotification *)nf {
    self.contentTV.text = [NSString stringWithFormat:@"%@\n%@\%@", self.contentTV.text, @"蓝牙数据发送失败了------", nf.object];
}
- (void)upgradeFail:(NSNotification *)nf {
    [ProgressHUD hideHUD];
    if (upgradingFlag) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            self.statusLabel.text = NSLocalizedString(@"Upgrade failed, please upgrade again~", @"");
            [ProgressHUD hideHUD];
            [ProgressHUD showErrorMessage:NSLocalizedString(@"Upgrade failed, please upgrade again~", @"")];
        });
        [self actionClean:nil];
    }
}

- (void)reciveData:(NSNotification *)nf {
    NSLog(@"----%@", nf.object);
    NSData *reciveData = nf.object;
    Byte *dataBytes = (Byte*)reciveData.bytes;
    if (reciveData.length >= 4 && dataBytes[2] == 0xFF && dataBytes[3] == 0xFD && !upgradingConnectCommandFlag) {
        upgradingConnectCommandFlag = YES;
        isUpgradAvailable = YES;
        [ProgressHUD showErrorMessage:NSLocalizedString(@"Successfully upgraded connection", @"")];
        return;
    }
    if (reciveData.length >= 4 && dataBytes[0] == 0x01 && dataBytes[1] == 0x10 && dataBytes[2] == 0xFF && dataBytes[3] == 0xFE) {
        if (!isUpgradingSlice) {
            isUpgradingSlice = YES;
            [self startUpgrading];
        }
    }else {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [ProgressHUD hideHUD];
            if (self->upgradingFlag) {
                self.statusLabel.text = NSLocalizedString(@"Upgrade failed, please upgrade again~", @"");
                [ProgressHUD showErrorMessage:NSLocalizedString(@"Upgrade failed, please upgrade again~", @"")];
                [self actionClean:nil];
            }
        });
    }
}

- (int)crcCheck:(Byte*)dataBuf length:(int)lenth {
    // Data指向要计算的CRC数组，Lenth为数据的有效长度
    int CRC = 0xFFFF;    //CRC的初始值
    int i, j;
    for (i = 0; i < lenth; i++) {
        CRC ^= dataBuf[i] & 0xff;                //和当前字节异或一次        //CRC ^= Data[i];
        CRC &= 0xffff;
        for (j = 0; j < 8; j++)    //每个字节循环8次
        {
            if ((CRC & 0x01) != 0) {
                CRC >>= 1;                //右移1位
                CRC ^= 0xA001;        //和多项式异或
                CRC &= 0xffff;
            } else {
                CRC >>= 1;                //右移1位
            }
        }
    }
    return CRC;
}

- (void)sendUpgradeConnectCommand {
    Byte sendbuf[11];
    sendbuf[0] = 0x01;
    sendbuf[1] = 0x10;
    sendbuf[2] = 0xFF;
    sendbuf[3] = 0xFD;
    sendbuf[4] = 0x00;
    sendbuf[5] = 0x01;
    sendbuf[6] = 0x02;
    sendbuf[7] = 0x00;
    sendbuf[8] = 0x00;
    sendbuf[9] = 0xBC;
    sendbuf[10] = 0xB2;

    [[BTManager sharedBTManager] sendCommand:sendbuf length:11];
}

- (void)sendUpgradeCompleteCommand {
    Byte senddataTemp[11];
    int i = 0;
    senddataTemp[i++] = 0x01;
    senddataTemp[i++] = 0x10;
    senddataTemp[i++] = (0xFFFF / 256);
    senddataTemp[i++] = (0xFFFF % 256);
    senddataTemp[i++] = (1 / 256);
    senddataTemp[i++] = (1 % 256);
    senddataTemp[i++] = 2;
    senddataTemp[i++] = 0;
    senddataTemp[i++] = 0;
    senddataTemp[i++] = 0XBD;
    senddataTemp[i++] = 0X50;

    [[BTManager sharedBTManager] sendCommand:senddataTemp length:11];
}

- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentAtURL:(NSURL *)url {
    NSLog(@"文件路径=%@", url);
    if (![url.absoluteString hasSuffix:@".bin"]) {
        [self dismissViewControllerAnimated: YES  completion: NULL];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [ProgressHUD showErrorMessage:@"Please select the correct bin file."];
        });
        return;
    }
    BOOL canAccessingResource = [url startAccessingSecurityScopedResource];
    if (canAccessingResource) {
        NSFileCoordinator *fileCoordinator = [[NSFileCoordinator alloc] init];
        NSError *error;
        [fileCoordinator coordinateReadingItemAtURL:url options:0 error:&error byAccessor:^(NSURL *newURL) {
            NSData *fileData = [NSData dataWithContentsOfURL:newURL];
            dispatch_async(dispatch_get_main_queue(), ^{
                [self loadFileData:url.absoluteString data:fileData];
            });
//            NSArray *arr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//            NSString *documentPath = [arr lastObject];
//            NSString *desFileName = [documentPath stringByAppendingPathComponent:@"myFile.pdf"];
//            [fileData writeToFile:desFileName atomically: YES ];
            [self  dismissViewControllerAnimated: YES  completion: NULL];
        }];
        [url stopAccessingSecurityScopedResource];
    }
}



@end
